`timescale 1ns / 1ps
/******************************************************************************
*                                                                             *
* UTICA softcore v0.1                                                         *
*                                                                             *
* Copyright (c) 2012 Andrew D. Zonenberg                                      *
* All rights reserved.                                                        *
*                                                                             *
* Redistribution and use in source and binary forms, with or without modifi-  *
* cation, are permitted provided that the following conditions are met:       *
*                                                                             *
*    * Redistributions of source code must retain the above copyright notice  *
*      this list of conditions and the following disclaimer.                  *
*                                                                             *
*    * Redistributions in binary form must reproduce the above copyright      *
*      notice, this list of conditions and the following disclaimer in the    *
*      documentation and/or other materials provided with the distribution.   *
*                                                                             *
*    * Neither the name of the author nor the names of any contributors may be*
*      used to endorse or promote products derived from this software without *
*      specific prior written permission.                                     *
*                                                                             *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF        *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN     *
* NO EVENT SHALL THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT,         *
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT    *
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,   *
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY       *
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT         *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF    *
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.           *
*                                                                             *
******************************************************************************/

/**
	@file UticaCPUMemStage.v
	@author Andrew D. Zonenberg
	@brief MEM stage of the pipeline
 */
module UticaCPUMemStage(
	clk,
	hold,
	mem_rdid, mem_rdval, mem_regwrite, mem_overflow_exception,
	mem_lw, mem_lb, mem_lbu, mem_lh, mem_lhu, mem_lowaddr, mem_mult, mem_multu, mem_mfhi, mem_mflo,
	writeback_lw, writeback_lb, writeback_lbu, writeback_lh, writeback_lhu, writeback_lowaddr, writeback_mult, writeback_multu,
	writeback_rdid, writeback_rdval, writeback_regwrite, writeback_mfhi, writeback_mflo
    );

	////////////////////////////////////////////////////////////////////////////////////////////////
	// IO declarations
	input wire clk;
	input wire hold;
		
	input wire[4:0] mem_rdid;
	input wire[31:0] mem_rdval;
	input wire mem_regwrite;
	input wire mem_overflow_exception;
	
	input wire mem_lw;
	input wire mem_lb;
	input wire mem_lbu;
	input wire mem_lh;
	input wire mem_lhu;
	input wire[1:0] mem_lowaddr;
	input wire mem_mult;
	input wire mem_multu;
	
	input wire mem_mfhi;
	input wire mem_mflo;
	
	output reg writeback_lw = 0;
	output reg writeback_lb = 0;
	output reg writeback_lbu = 0;
	output reg writeback_lh = 0;
	output reg writeback_lhu = 0;
	output reg[1:0] writeback_lowaddr = 0;
	output reg writeback_mult = 0;
	output reg writeback_multu = 0;
	
	output reg writeback_mfhi = 0;
	output reg writeback_mflo = 0;
	
	output reg[4:0] writeback_rdid = 0;
	output reg[31:0] writeback_rdval = 0;
	output reg writeback_regwrite = 0;
	
	////////////////////////////////////////////////////////////////////////////////////////////////
	// MEM stage
	
	always @(posedge clk) begin	
		if(!hold) begin
		
			writeback_lw <= 0;
			writeback_lb <= 0;
			writeback_lbu <= 0;
			writeback_lh <= 0;
			writeback_lhu <= 0;
			writeback_mult <= 0;
			writeback_multu <= 0;
			
			writeback_mfhi <= mem_mfhi;
			writeback_mflo <= mem_mflo;
			
			writeback_lowaddr <= mem_lowaddr;
		
			if(mem_overflow_exception) begin
				$display("[UticaCPU] WARNING: Overflow exception not implemented");
			end
		
			//Push stuff down the pipe
			//During this cycle we're waiting for the L1 cache to respond
			if(mem_lw | mem_lb | mem_lbu | mem_lh | mem_lhu) begin
				writeback_rdid <= mem_rdid;
				writeback_lw <= mem_lw;
				writeback_lb <= mem_lb;
				writeback_lbu <= mem_lbu;
				writeback_lh <= mem_lh;
				writeback_lhu <= mem_lhu;
				writeback_regwrite <= 1;
			end
						
			//Waiting for multiplier, just push "waiting" state down the pipe
			else if(mem_mult) begin
				writeback_mult <= 1;
			end
			else if(mem_multu) begin
				writeback_multu <= 1;
			end
			
			//Default - no long instructions going on
			//Just pass stuff down to the writeback stage
			//TODO: For multicycle instructions like multiply, pull the "real" value.
			else begin
				writeback_rdid <= mem_rdid;
				writeback_rdval <= mem_rdval;
				writeback_regwrite <= mem_regwrite;
			end
		
		end
	end

endmodule
